【第2960期】原生 popover 终于要来了!
前言
作为个人可太欢喜这种浏览器自带的功能了。今日前端早读课文章由 @XboxYan 分享,公号:前端侦探授权。
@XboxYan,阅文体验设计部,专注用户体验相关,热爱 CSS,热爱原生,github:https://github.com/XboxYan
前端早读课:与你分享” 我 “的技术视界
正文从这开始~~
提到 popover,相信大家都很熟悉,没错,就是组件库里经常见到的悬浮层(或者叫 “气泡卡片”),比如 Ant Design。
现在,这个好用的特性终于在 Chrome 114 上正式支持了~下面花几分钟快速了解一下吧
一、popover 属性
其实这个名称以前叫做 popup,后来才更改成了 popover😂。
popover 是一个全局属性。给任意元素添加 popover 以后,它就变成了一个悬浮层。
<div popover>我是悬浮层</div>
popover 有两个值,分别是
auto:自动(默认值)。也就是浏览器默认行为,比如点击悬浮层外面会关闭悬浮层,按键盘 Esc 键也会关闭悬浮层
manual:手动。也就是没有前面的默认行为,所有操作必须由开发者手动控制。
<div popover>我是悬浮层</div>
<div popover="auto">我是悬浮层</div>
<div popover="manual">我是悬浮层</div>
悬浮层默认是隐藏的,也不能通过属性设置默认显示。那么,如何打开一个悬浮层呢?
二、控制悬浮层的方式
控制悬浮层有两种方式,分别是 声明式 和 命令式
首先来看声明式,经常写原生 HTML 的应该会很喜欢这种方式,无需 JS 介入就可以实现悬浮层的打开和关闭,如下
<button popovertarget="pop1">打开 auto 悬浮层</button>
<div id="pop1" popover>我是 auto 悬浮层</div>
只需要通过 popovertarget 属性将目标悬浮层的 id 属性和按钮相关联就行了(注意,只能是 ID),效果如下
还可以通过 popovertargetaction 属性来设置点击行为,有三个值,分别是
show:打开。
hide:关闭。
toggle:切换(默认值)。如果悬浮层是关闭的就打开,反正亦然
<button popovertarget="pop1" popovertargetaction="show">打开 auto 悬浮层</button>
<button popovertarget="pop1" popovertargetaction="hide">关闭 auto 悬浮层</button>
<button popovertarget="pop1" popovertargetaction="toggle">切换 auto 悬浮层</button>
<div id="pop1" popover>我是 auto 悬浮层</div>
效果如下
现在回过头来看看两种 popover 的区别
<button popovertarget="pop1">切换 auto 悬浮层</button>
<button popovertarget="pop2">切换 manual 悬浮层</button>
<div id="pop1" popover>我是 auto 悬浮层</div>
<div id="pop2" popover="manual">我是 manual 悬浮层</div>
效果如下
可以看到,auto 悬浮层点击空白会自动关闭(还可以通过 Esc 键关闭),而 manual 悬浮层只能手动去关闭。当然大部分情况下 auto 可以满足需求。
三、命令式方式
所谓 “命令式”,其实就是一套 JS API,需要在 JS 中主动去调用。
那么,有了声明式为啥还要命令式呢?答案是,更灵活。
比如,前面的声明式,只适用于 click 场景,如果需要 hover 也能打开悬浮层,这种方式就不行了。像这种情况,就可以采用命令式方式了。
先看语法,很简单,就是 3 个方法
popoverEl.showPopover(); // 打开
popoverEl.hidePopover(); // 关闭
popoverEl.togglePopover(force) // 切换,可传参数,强制设置为 true 或者 false
需要注意的是,这 3 个方式仅适用于悬浮层,也就是必须有 popover 属性,如果是普通元素,会直接报错,如下
还有一种情况,如果一个本来已经打开的悬浮层,再次调用 showPopover (),也会报错,反之亦然
因此,在使用 JS 控制时,推荐使用 manual 悬浮层,便于精准控制。
下面来看一个 hover 控制的例子
<button id="button">hover 打开悬浮层</button>
<div id="pop" popover="manual">我是 hover 悬浮层</div>
然后是相关 JS
button.addEventListener('mouseenter', () => {
pop.showPopover()
})
button.addEventListener('mouseleave', () => {
pop.hidePopover()
})
效果如下
四、判断悬浮层的打开状态
首先,从 HTML 结构上来看,打开和关闭没有任何属性变化,这个和 details 不一样(details 会添加 open 属性)。为此,CSS 还专门出了一个伪类:open 用于标识悬浮层的打开状态
目前还不稳定,后续可能会更变为:popover-open
div[popover]:open{
/* 打开样式 */
}
通过这个伪类,我们可以很轻松的给悬浮层添加过渡动画
[popover]{
display: block; /*默认是display:none,不会有动画*/
visibility: hidden;
opacity: 0;
transform: scale(.6);
transition: .3s;
}
[popover]:open{
visibility: visible;
transform: scale(1);
opacity: 1;
}
效果如下
除了 CSS 方式,JS 也能判断悬浮层的状态,但是并不是自己想象的那样。
起初,我以为有一个属性可以直接获取到悬浮层的状态,发现并不行,如下
popoverEl.open // undefined
那如何获取呢?
其实可以借助前面 CSS 的方式,只要匹配的:open 伪类不就可以了吗,需要用到 matches 方法,https://developer.mozilla.org/en-US/docs/Web/API/Element/matches
这样就能随时获取到悬浮层的打开状态了
popoverEl.matches(':open')
另外,还可以通过事件监听的方式来获取,需要用到新的事件 toggle,这是一个专门针对 popover 新推出的事件,使用方式如下
popoverEl.addEventListener("toggle", (event) => {
if (event.newState === "open") {
console.log("打开状态");
} else {
console.log("关闭状态");
}
});
五、popover 的顶层特性
前面说了那么多,好像并没有什么很厉害的地方,随便一个 div 都可以模拟,而且现在的组件库不是也实现的好好的吗?到底有什么优势呢?
打开控制台可以看到,popover 上有一个很特殊的标识
这个就是顶层 top-layer !也就是层级是最高的,高于页面上的一切。
这也是悬浮层的意义所在,本身就应该是悬浮在最上面。下面是示意图
这样的好处就是无论在 HTML 中的任何位置,都无需担心悬浮层被遮挡的情况,也无需将悬浮层移动的最外层 body 上。
Demo:https://codepen.io/xboxyan/pen/MWPrRod
如果浏览器不支持,会有下面提示
这个是用 @supports 实现的
@supports selector([popover]:open) {
.no-support{
display: none ;
}
}
六、兼容性和总结
看一下兼容性,目前只有 Chrome 114 + 支持,内部项目可以尝鲜一下,如果是 Electron 应用,那就大胆使用吧
下面来总结一下本文要点:
popover 是一个全局属性。给任意元素添加 popover 以后,它就变成了一个悬浮层。
popover 属性有两个值,默认是 auto 自动模式,支持默认行为,比如点击空白关闭,键盘 Esc 关闭
popover 属性还支持 manual 手动模式,也就是没有以上默认行为
控制 popover 有两种方式,分别是声明式和命令式
声明式是指通过 HTML 属性来实现点击交互
可以通过 popovertarget 属性将悬浮层的 id 和按钮相关联,这样就能通过按钮打开悬浮层了
还可以通过 popovertargetaction 属性来设置点击行为,有 show、hide、toggle3 种方式
命令式是指通过 JS API 来实现对悬浮层的控制,相比声明式而言更加灵活
控制悬浮层的方法有 showPopover、hidePopover、togglePopover
CSS 伪类
:open
可以区分悬浮层的打开状态JS 可以通过
matches(':open')
来获取悬浮层的打开状态JS 还可以通过监听 toggle 事件来获取悬浮层的打开状态,方式是
event.newState
相比传统实现,原生 popover 最大的优势是支持顶层特性
关于本文
作者:@XboxYan
原文:https://mp.weixin.qq.com/s/qsZOrUBEjhWGUJ_qzF4XIw
这期前端早读课
对你有帮助,帮” 赞 “一下,
期待下一期,帮” 在看” 一下 。